module	sdram_dqm_test(
						sclk,
						resetb,
						test_start,
						w_data,
						test_end,
						unmatch,
						sdram_cnt,
						sdram_addr,
						sdram_oeb,
						r_data,
						dqm_cmd,
						work_on);
						
parameter		Sdram_A_Width=13;
parameter		Sdram_D_Width=32;
parameter		Sdram_C_Width=4;
parameter		Optional_time=4;
parameter		Input_delay=1;
parameter		Output_delay=1;
parameter		base_length=12+Input_delay+Output_delay+Optional_time;
//parameter		cycle_length=Sdram_C_Width-1;
parameter		cycle_length=Sdram_C_Width/2-1;

parameter		dqm_1st_data=32'h00000000;
parameter		dqm_2nd_data=32'hffffffff;						
						
input			sclk,
				resetb;

input			test_start;
input	[Sdram_D_Width-1:0]	r_data;

output			test_end;
output			unmatch;
output			work_on;

output	[4:0]	sdram_cnt;
output			sdram_oeb;
output	[Sdram_A_Width-1:0]	sdram_addr;	
output	[Sdram_D_Width-1:0]	w_data;
output	[Sdram_C_Width-1:0]	dqm_cmd;

reg		[Sdram_C_Width-1:0]	dqm_cmd;
reg				test_start_last;
reg				test_end;
reg				unmatch,work_on,work_on_last;
reg				sdram_oeb;
reg		[Sdram_D_Width-1:0]	w_data;
reg		[4:0]	command;
reg		[6:0]	base_count;
reg		[6:0]	cycle_count;
reg				base_end,cycle_end;
reg		[31:0]	temp;
reg		[Sdram_C_Width-1:0]	shift;
//reg		[Sdram_D_Width-1:0]	compare_data;

parameter	Mode_Reg_Set	=5'b00000;
parameter	Auto_Refresh	=5'b00010;
parameter	Row_Active	=5'b00110;
parameter	Pre_Charge	=5'b00100;
parameter	PreCharge_All	=5'b00101;
parameter	Write		=5'b01000;
parameter	Write_Pre	=5'b01001;
parameter	Read		=5'b01010;
parameter	Read_Pre	=5'b01011;
parameter	Nop		=5'b01110;
parameter	Dsel		=5'b11110;


always	@(posedge sclk or negedge resetb)
	if (resetb==0)
		test_start_last<=0;
	else 
		test_start_last<=test_start;
		
always	@(posedge sclk or negedge resetb)
	if (resetb==0)
		work_on<=0;
	else if (base_end==1 && cycle_end==1)
		work_on<=0;
	else if (test_start_last==1 && test_start==0)
		work_on<=1;
		
always	@(posedge sclk or negedge resetb)
	if (resetb==0)
		work_on_last<=0;
	else
		work_on_last<=work_on;			
		
always	@(posedge sclk or negedge resetb)
	if (resetb==0)
		test_end<=0;
	else if (work_on==0 && work_on_last==1)
		test_end<=1;
	else
		test_end<=0;			
		
always	@(posedge sclk or negedge resetb)
	if (resetb==0)
		base_count<=0;
	else if (base_end==1 || work_on==0)
		base_count<=0;
	else
		base_count<=base_count+1;
		
always	@(posedge sclk or negedge resetb)
	if (resetb==0)
		base_end<=0;
	else if (base_count==base_length)
		base_end<=1;
	else
		base_end<=0;
		
always	@(posedge sclk or negedge resetb)
	if (resetb==0)
		cycle_count<=0;
	else if (work_on==0)
		cycle_count<=0;
	else if (base_end==1)
		cycle_count<=cycle_count+1;
		
always	@(posedge sclk or negedge resetb)
	if (resetb==0)
		cycle_end<=0;
	else if (cycle_count==cycle_length)
		cycle_end<=1;
	else
		cycle_end<=0;
		
//always	@(posedge sclk or negedge resetb)
//	if (resetb==0)
//		temp<=32'hffffff00;
//	else if(base_end==1)
//		case(cycle_count)
//			7'h00:		temp<=32'hffff00ff;
//			7'h01:		temp<=32'hff00ffff;
//			7'h02:		temp<=32'h00ffffff;
//			default:	temp<=32'hffffff00;
//		endcase	
//	else if (work_on==0)
//		temp<=32'hffffff00;	
		
always	@(posedge sclk or negedge resetb)
	if (resetb==0)
		temp<=32'hffff0000;
	else if (base_end==1)
		case(cycle_count)
			7'h00:		temp<=32'h0000ffff;
			default:	temp<=32'hffff0000;
		endcase
	else if (work_on==0)
		temp<=32'hffff0000;				
				
		
assign		sdram_cnt[4]=1;
assign		sdram_cnt[3:0]=command[4:1];
assign		sdram_addr=0;								
										
always	@(posedge sclk or negedge resetb)
	if (resetb==0)
		command<=Nop;
	else
		case(base_count)
			7'h02:		command<=Row_Active;
			7'h05:		command<=Write;
			7'h08:		command<=Write;
			7'h0b:		command<=Read;
			7'h0e:		command<=Pre_Charge;
			default:	command<=Nop;
		endcase
		
always	@(posedge sclk or negedge resetb)
	if (resetb==0)
		shift<=4'b0011;
	else if (base_end==1 && cycle_end==1)
		shift<=4'b0011;
	else if (base_end==1)
		shift<={shift[1:0],2'b00};		
		
//always	@(posedge sclk or negedge resetb)
//	if (resetb==0)
//		shift<=1;
//	else if (base_end==1 && cycle_end==1)
//		shift<=1;
//	else if (base_end==1)
//		shift<={shift[Sdram_C_Width-2:0],1'b0};
		
always	@(posedge sclk or negedge resetb)
	if (resetb==0)
		dqm_cmd<=0;
//	else if (base_count==7'h08)
	else if (base_count<=7'h09 && base_count>=7'h07 )
		dqm_cmd<=shift;
	else
		dqm_cmd<=0;
		
always	@(posedge sclk or negedge resetb)
	if (resetb==0)
		w_data<=0;
	else
		case(base_count)
			7'h05:		w_data<=dqm_1st_data;
			7'h08:		w_data<=dqm_2nd_data;
			default:	w_data<=0;
		endcase
																																	
always	@(posedge sclk or negedge resetb)
	if (resetb==0)
		sdram_oeb<=0;
	else
			case(base_count)

			2,3,4,5,6,7,8,9:		sdram_oeb<=1;
			default:	sdram_oeb<=0;
			endcase
		
		

//always	@(posedge sclk or negedge resetb)
//always	@(negedge sclk or negedge resetb)
//	if (resetb==0)
//		unmatch<=0;
//	else if (base_count==base_length-Optional_time)
//	begin
//		if (r_data!==temp[Sdram_D_Width-1:0])
//			unmatch<=1;
//		else
//			unmatch<=0;
//	end		
//	else
//			unmatch<=0;
			
reg		flag_comp1,unmatch_tmp;				
			
always	@(posedge sclk or negedge resetb)
	if (resetb==0)
		flag_comp1<=0;
	else if (base_count==(base_length-Optional_time+3))
		flag_comp1<=1;
	else
		flag_comp1<=0;
		
always	@(posedge sclk or negedge resetb)
	if (resetb==0)
		unmatch_tmp<=0;
	else if (r_data==temp[Sdram_D_Width-1:0])
		unmatch_tmp<=0;
	else
		unmatch_tmp<=1;
		
always	@(posedge sclk or negedge resetb)
	if (resetb==0)
		unmatch<=0;
	else if (flag_comp1==1)
		unmatch<=unmatch_tmp;
	else
		unmatch<=0;														
			
endmodule																	